package com.lfy.java8.functioninterface;


import java.util.function.*;

/**
 * 在 java.util.function 包中，有几个内置的函数式接口； 消费者，生产者；
 *   消费：会要参数；  生产：会有返回值；
 *
 *  1、Function<T, R>： T参数，R返回；  有参，有返回值； 消费/生产型函数
 *  2、Consumer<T>：    T参数，无返回值；  有参，无返回值；  消费型函数
 *  3、Supplier<T>：    无参数，T返回值；  无参，有返回值；  生产型函数
 *  4、Predicate<T>：   T参数，boolean返回值； 有参，有返回值； 判断型函数； 【断言机制】；
 *
 *
 * 理解 Function 的变体
 *  Function<T,Void> = Consumer<T>
 *  Function<T,Boolean> = Predicate<T>
 *  Function<Void,T> = Supplier<T>
 */
public class FunctionTest {




    /**
     * 系统内置的函数式接口
     * @param args
     */
    public static void main(String[] args) {

        Function<String, Integer> function = niu666();
        Integer world = function.apply("hello world");
        System.out.println(world);


        //4、Predicate： 断言机制
        Predicate<Integer> isEven = (t) -> t%2 == 0;
        boolean test = isEven.test(13);
        System.out.println("isEven："+test);



        // 这种以后用的非常多；
        // 你发现，你调用的这个方法，需要传入一个函数式接口，函数式接口可以被简化为Lambda表达式；
        // 以后传入lambda表达式，就是传入一个函数式接口的实现；
        helloEee(()-> "hello world");



//        IntConsumer： 只消费指定类型参数
        //3、生产型函数
        Supplier  sup1 = () -> "hello leifengyang";


        helloEee(sup1);
//        Object o = sup1.get();
//        System.out.println("sup1："+o);


        //2、消费型函数
        Consumer<String> print = (t) -> System.out.println(t);
        helloDef(print);
//        print.accept("hello world");


        System.out.println("----------------");

        //1、编写了一个 【函数类型】 的对象
        Function<String,String> upper = (t) -> t.toUpperCase() + "!";
        String s = helloAbc(upper);
        System.out.println(s);


        Function<String,String> subStr = (t) -> t.substring(0,3);
        String s1 = helloAbc(subStr);
        System.out.println(s1);
    }

    public static Function<String,Integer> niu666(){
        Function<String,Integer> f = (t) -> t.length();
        return f;
    }
    public static Object  helloEee(Supplier abc){
        Object o = abc.get();
        System.out.println("准备打印： " + o);
        return o;
    }
    public static String helloDef(Consumer<String> abc){
        System.out.println("准备执行 helloDef ");
        String str = "hello world";
        abc.accept(str);  // 这行有可能还不是打印。 abc

        return "xxxx";
    }

    /**
     * abc 此时是一个方法对象【代表【函数的对象】】；
     * @param abc
     * @return
     */
    public static String helloAbc(/*传入一个方法 a*/ Function<String,String> abc){

        //回调机制(Callback)： apply 的功能 不一定是什么
        //钩子函数(hook)：
        String res = abc.apply("leifengyang");

        return "abc! "+ res;
    }


    //我们定义了一个普通方法；
    //局限性：方法不属于任何类型：以前的Java，不能把方法作为参数传递(拿不到方法的引用作为传递)、或者作为返回值传递
    public String uppperStr(String str){
        return str.toUpperCase() + "!";
    }
    public static void myfunction(String[] args) {
        MathOperation add = (x, y) -> {
            System.out.println("执行了add方法");
            return x + y;
        };


        MathOperation divide = (x, y) -> x/y;


        int operate = add.operate(10, 2);
        System.out.println(operate);

        int operate1 = divide.operate(10, 2);
        System.out.println(operate1);
    }
}
